using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Windows.Forms;

namespace fbn_episodes
{
    class BackParser
    {
        String BackFile;
        XmlTextReader reader;
        XmlTextWriter output;
        struct finder
        {
            public string element;
            public int count;
        }

        bool f_render;
        bool f_find;
        bool f_portal;
        bool f_region;
        bool f_mouse;
        bool f_push;
        bool f_click;
        int KusokCount;
        finder TempFind;


        public Stack<string> render;
        Stack<finder> find;
        Stack<string> region;
        Stack<string> push;
        Stack<string> portal;
        Stack<string> click;
        Stack<string> mouse;

        public BackParser()
        {
    
            render = new Stack<string>();
            find = new Stack<finder>();
            region = new Stack<string>();
            push = new Stack<string>();
            portal = new Stack<string>();
            mouse = new Stack<string>();
            click = new Stack<string>();
        }

        public void BackParse(string XmlFile)
        {
            BackFile = XmlFile;
            reader = new XmlTextReader(XmlFile);
            reader.WhitespaceHandling = WhitespaceHandling.None;
            KusokCount = 0;
            
            while (reader.Read())
            {
                if (reader.NodeType == XmlNodeType.Element)
                {
                    switch (reader.Name)
                    {
                        case "RenderObject": f_render = true; break;
                        case "find": f_find = true; break;
                        case "mouse": f_mouse = true; break;
                        case "portal": f_portal = true; break;
                        case "push": f_push = true; break;
                        case "region": f_region = true; break;
                        case "click": f_click = true; break;
                        case "Kusok": KusokCount++; break;
                        case "Object": ObjectParse(); break;
                    }

                }

                if (reader.NodeType == XmlNodeType.EndElement)
                {
                    switch (reader.Name)
                    {
                        case "RenderObject": f_render = false; break;
                        case "find": f_find = false; break;
                        case "mouse": f_mouse = false; break;
                        case "portal": f_portal = false; break;
                        case "push": f_push = false; break;
                        case "region": f_region = false; break;
                        case "click": f_click = false; break;
                        case "Object": ObjectEnd(); break;
                    }

                }
            }
        }

        private void ObjectParse()
        {
            if (reader.AttributeCount > 0)
            {
                if (f_render)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "NameModel")
                    {
                        render.Push(reader.Value);
                    }
                }

                if (f_find)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        TempFind = new finder();
                        TempFind.element = reader.Value;
                        find.Push(TempFind);

                    }
                }
                if (f_mouse)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        mouse.Push(reader.Value);
                    }
                }

                if (f_portal)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        portal.Push(reader.Value);
                    }
                }

                if (f_push)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        push.Push(reader.Value);
                    }
                }

                if (f_region)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        region.Push(reader.Value);
                    }
                }

                if (f_click)
                {
                    reader.MoveToFirstAttribute();
                    if (reader.Name == "Name")
                    {
                        click.Push(reader.Value);
                    }
                }
            }
        }

        private void ObjectEnd()
        {
            if (f_find)
            {
                TempFind = find.Pop();
                TempFind.count = KusokCount;
                find.Push(TempFind);
                KusokCount = 0;
            }
        }


        public XmlNode BackRnd(bool reg, string BFile, CheckedListBox.CheckedItemCollection chkItems)
        {
            int RegCount = 0;
            output = new XmlTextWriter("newback.xml", Encoding.Unicode);
            output.Formatting = Formatting.Indented;
            output.WriteStartDocument();
            if (reg)
                output.WriteStartElement("Region");
            else
                output.WriteStartElement("Back");
            output.WriteAttributeString("Name", BFile);
            output.WriteStartElement("Beg");
            output.WriteAttributeString("Value", "1");
            output.WriteEndElement();
            output.WriteStartElement("Actions");
            output.WriteStartElement("Action");
            output.WriteAttributeString("Name", "a_init");
            //Back Init
            foreach (string s in render)
            {
                
                if(!reg)
                {
                    if (chkItems.Contains(s))
                    {
                        output.WriteStartElement("Visible");
                        output.WriteAttributeString("Type", "Obj");
                        output.WriteAttributeString("par1", s);
                        output.WriteAttributeString("par_i1", "0");
                        output.WriteEndElement();
                    }
                }
                else
                {
                    if (((s.Substring(0, 2) == "S_") && !((s.Length >= 7) && (s.Substring(0, 7).ToLower() == "S_kusok".ToLower())) && !((s.Length >= 6) && (s.Substring(0, 6).ToLower() == "S_back".ToLower()))) || (s.Substring(0, 2) == "A_") || (s.Substring(0, 2) == "O_"))
                    {
                        output.WriteStartElement("Visible");
                        output.WriteAttributeString("Type", "Obj");
                        output.WriteAttributeString("par1", s);
                        output.WriteAttributeString("par_i1", "0");
                        output.WriteEndElement();
                    }
                }
                

            }
            if (portal.Count > 0) output.WriteComment("////////////////////// Open portal /////////////////////////////");
            foreach (string s in portal)
            {
                output.WriteStartElement("Open");
                output.WriteAttributeString("Type", "Sadanie_simple");
                output.WriteAttributeString("par1", "portal");
                output.WriteAttributeString("par2", s);
                output.WriteEndElement();
            }
            if (region.Count > 0) output.WriteComment("////////////////////// Open region /////////////////////////////");
            foreach (string s in region)
            {
                output.WriteStartElement("Open");
                output.WriteAttributeString("Type", "Sadanie_simple");
                output.WriteAttributeString("par1", "region");
                output.WriteAttributeString("par2", s);
                output.WriteEndElement();
            }
            if(find.Count > 0)output.WriteComment("////////////////////// Open find /////////////////////////////");
            foreach (finder f in find)
            {
                
                if ((f.count > 0) && (!reg))
                {
                    output.WriteStartElement("Open");
                    output.WriteAttributeString("Type", "Sadanie_complex");
                    output.WriteAttributeString("par1", "find");
                    output.WriteAttributeString("par2", f.element);
                    output.WriteEndElement();
                }
                else
                {
                    output.WriteStartElement("Open");
                    output.WriteAttributeString("Type", "Sadanie_simple");
                    output.WriteAttributeString("par1", "find");
                    output.WriteAttributeString("par2", f.element);
                    output.WriteEndElement();
                }
                
            }
            if (push.Count > 0) output.WriteComment("////////////////////// Open push /////////////////////////////");
            foreach (string s in push)
            {
                output.WriteStartElement("Open");
                output.WriteAttributeString("Type", "Sadanie_simple");
                output.WriteAttributeString("par1", "push");
                output.WriteAttributeString("par2", s);
                output.WriteEndElement();
            }

            if (mouse.Count > 0) output.WriteComment("////////////////////// Open mouse /////////////////////////////");
            foreach (string s in mouse)
            {
                output.WriteStartElement("Open");
                output.WriteAttributeString("Type", "Sadanie_simple");
                output.WriteAttributeString("par1", "mouse");
                output.WriteAttributeString("par2", s);
                output.WriteEndElement();
            }
            if (click.Count > 0) output.WriteComment("////////////////////// Open click /////////////////////////////");
            foreach (string s in click)
            {
                output.WriteStartElement("Open");
                output.WriteAttributeString("Type", "Sadanie_simple");
                output.WriteAttributeString("par1", "click");
                output.WriteAttributeString("par2", s);
                output.WriteEndElement();
            }
            output.WriteEndElement(); //Action Init
            foreach (finder f in find)
            {
                if ((f.count > 0)&&(!reg))
                {
                    output.WriteStartElement("Action");
                    output.WriteAttributeString("Name", "del_find_" + f.element);
                    output.WriteStartElement("Add");
                    output.WriteAttributeString("Type", "Predmet");
                    output.WriteAttributeString("par1", f.element);
                    output.WriteAttributeString("par2", "down_panel");
                    output.WriteEndElement();
                    output.WriteEndElement();
                }   
                else
                {
                    output.WriteStartElement("Action");
                    output.WriteAttributeString("Name", "del_find_" + f.element);
                    output.WriteStartElement("Add");
                    output.WriteAttributeString("Type", "Predmet");
                    output.WriteAttributeString("par1", f.element);
                    output.WriteAttributeString("par2", "predmet_menu");
                    output.WriteEndElement();
                    output.WriteEndElement();
                }
                    
               
            }
            foreach (string s in push)
            {
                
                output.WriteStartElement("Action");
                output.WriteAttributeString("Name", "del_push_" + s);
                output.WriteStartElement("Delete");
                output.WriteAttributeString("Type", "Predmet");
                output.WriteAttributeString("par1", s);
                output.WriteEndElement();
                output.WriteEndElement();
            }
            foreach (string s in portal)
            {
                
                output.WriteStartElement("Action");
                output.WriteAttributeString("Name", "mc_portal_" + s);
                output.WriteStartElement("Run");
                output.WriteAttributeString("Type", "Action");
                output.WriteAttributeString("par1", "a_open_back_" + s.Substring(0, 2) +"B"+ s.Substring(s.Length-1, 1));
                output.WriteEndElement();
                output.WriteEndElement();
            }

            foreach (string s in region)
            {
                RegCount++;
                
                output.WriteStartElement("Action");
                output.WriteAttributeString("Name", "mc_region_" + s);
                output.WriteStartElement("Run");
                output.WriteAttributeString("Type", "Region");
                output.WriteAttributeString("par1", BFile.Remove(BFile.Length - 4) + "_reg_" + RegCount.ToString() + ".xml");
                output.WriteEndElement();
                output.WriteEndElement();
            }
            foreach (string s in mouse)
            {
                RegCount++;
                output.WriteStartElement("Action");
                output.WriteAttributeString("Name", "del_mouse_" + s);
                output.WriteFullEndElement();
            }
            output.WriteEndElement(); //Actions
            output.WriteEndElement(); //Back
            output.WriteEndDocument();
            output.Close();
            XmlDocument BackTemp = new XmlDocument();
            BackTemp.Load("newback.xml");
            XmlNode BackNode;
            if(reg)
               BackNode  = BackTemp.SelectSingleNode("/Region");
            else
               BackNode = BackTemp.SelectSingleNode("/Back");

           
           return BackNode;

        }

    
    }
}
